/*
 * Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
 *
 * Licensed under the Mulan PSL v2.
 * You can use this file according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of the License at
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
 * FOR MORE DETAILS.
 */

#pragma once

#include <cstdint>
#include <map>
#include <string>
#include <vector>

#include "boost/algorithm/string.hpp"

#include "DataStructure/Common/Id.h"
#include "DataStructure/Common/Real.h"
#include "DataStructure/Input/Solver/Subcase.h"

#include "Import/ImportAPI/Common/ImportNamespace.h"

SG_IMPORT_BDF_NAMESPACE_OPEN

static const size_t SIGNELINE_FIELDCOUNT = 10;   ///> 当行最大FIELD个数
static const size_t ALL_FIELDCOUNT       = 500;  // 一个词条的总FIELD个数

static const size_t ENTRYSZIE       = 8;         // 每行第一个FIELD所占字符
static const size_t SMALLFOEMATSZIE = 8;         // 短格式每个FIELD所占字符
static const size_t LARGEFOEMATSZIE = 16;        // 长格式每个FIELD所占字符

/**
 * @brief 结构体用于存储解析 Conrol 中单行的信息。
 *
 * 例如：解析行 "AUTOSPC (PRINT, PUNCH, SID=100, EPS=1.E-6, MPC)=YES"
 * 解析后的数据存储在结构体中。结构体包含四个部分：
 * - `m_Key`：主键，例如上例中的 "AUTOSPC"。
 * - `m_vaule`：等号右侧的值，例如 "YES"。
 * - `m_vecKeys`：括号内可选参数的集合，以键的形式存储，例如 "PRINT" 和 "PUNCH"。
 * - `m_mapKeys`：括号内参数带值的键值对集合，例如 "SID=100" 和 "EPS=1.E-6"。
 */

/**
 * @brief 解析案例控制行，将其分解为键和值。
 *
 * @param[in] inputLine  输入字符串，格式可以是 "KEY=VALUE" 或 "KEY(VALUE1, VALUE2, SID=100)=VALUE"。
 * @param[out] ControlInfo  输出的结构体。
 *
 * @throws std::logic_error 如果输入字符串不符合预期格式。
 *
 * - 如果字符串包含括号，则提取括号内的参数。
 * - 括号内的参数会被分为带等号的键值对（存储在 m_mapKeys 中）和不带等号的参数（存储在 m_vecKeys 中）。
 * - 如果字符串不包含括号，直接提取等号前后的值。
 */
void parseCaseControlLine (const std::string& inputLine, _OUT SG::DataStructure::FEM::Subcase::ControlInfo& controlInfo);

/**
 * @brief 解析控制行(eg: sol 101,eg:subcase 1)，将其分解为键和值。
 *
 * @param[in] inputLine  输入字符串，格式可以是 " A  B"
 * @param[out] ControlInfo  输出的结构体。
 *
 *
 * - 去掉前后空格后，字符串被空格分割，分割后的字符串必须第一个和最后一个未非空字符串，其余为空字符串
 */
bool parseDoubleField (const std::string& inputLine, _OUT SG::DataStructure::FEM::Subcase::ControlInfo& controlInfo);

// BDF文件格式
enum BDFFORMAT : std::uint8_t
{
    BDFFORMAT_FREE  = 0,
    BDFFORMAT_SMALL = 1,  // 8位
    BDFFORMAT_LARGE = 2,  // 16位
    BDFFORMAT_SET   = 3,  // set格式的，SET       990010      =   105875  105678 或者逗号分割的 SET 1 = 41,126,169 THRU 238,239
};

/**
 * @brief 将字符串转换为科学记数法形式
 *
 * @param str 输入的字符串，它将被修改以符合科学记数法的格式（如果满足条件）
 * @return 如果字符串代表一个浮点数（即包含小数点或'e'/'E'表示指数），则返回true；否则返回false
 */
bool covertToScientificNotation (std::string& str);

/**
 * @brief 将字符串转换为双精度浮点数,并调整科学技术法形式
 *
 * @param str 输入的字符串
 * @return 如果字符串不能被转换为双精度浮点数将抛出异常，并返回0.0
 */
SG::DataStructure::Common::Real convertToReal (std::string& str);

/**
 * @brief 将字符串为64位整型
 *
 * @param str 输入的字符串
 * @return 如果字符串不能被转换为64位整型将抛出异常，并返回0
 */
SG::DataStructure::Common::I64 convertToI64 (std::string& str);

/**
 * @brief 判断是否全为空格
 *
 * @param str 输入的字符串
 * @return
 */
bool is_all_space (std::string& str);

/**
 * @brief 获取行格式
 *
 * 根据给定的字符串（StrLine）中的特定字符判断并返回对应的行格式。
 * 如果字符串中包含逗号（,），则返回BDFFORMAT_FREE格式。
 * 如果字符串中包含星号（*），则返回BDFFORMAT_LARGE格式。
 * 如果字符串中既不包含逗号也不包含星号，则返回BDFFORMAT_SMALL格式。
 *
 * @param StrLine 输入的字符串，用于判断其格式
 * @return 返回字符串对应的行格式枚举值
 */
BDFFORMAT getBulkLineFormat (std::string& StrLine);

/**
 * @brief 分割条目信息
 *
 * 此函数将给定的条目信息行（LineEntryInfo）根据特定格式分割成多个条目，并将这些条目存储到新的向量（dividedEntryInfo）中。
 *
 * @param[in,out] BulkCompleteLine 存储原始条目信息行的向量。
 * @param[out] BulkField 存储分割后的条目信息的向量。
 * @return 返回true，表示操作成功完成。
 */
bool divideBulkEntry (std::vector<std::string>& BulkCompleteLine, std::vector<std::string>& BulkField);

/**
 * @brief 找到此行最后一个非空词条的索引
 *
 * 找到row行的最后一个非空filed的下标，[倒数第二个,正数第二个]
 *
 * @param[in] data 待查询的词条vector。
 * @param[in] row 查询的行数，从0开始。
 * @return -1 ，这一行每个元素均为空元素。
 *         非-1，非空下标
 */
int findNonEmptyIndex (const std::vector<std::string>& data, size_t row);

/**
 * @brief 分割自由模式，区分空格与逗号
 *
 *
 * @param[in] inputStr 待分割的字符串。
 * @return 分割后的vector
 */
std::vector<std::string> divideFreeForm (std::string& inputStr);

/**  @brief  获取一个全局唯一的虚节点ID
 *
 * @return
 * @author   wuxingchuang
 * @date     2025.04.08
 */
SG::DataStructure::Common::I64 getVirtualGridId ();

SG_IMPORT_BDF_NAMESPACE_CLOSE
